package com.huihe.framework.service;

import com.huihe.common.enums.DelFlagEnum;
import com.huihe.common.enums.DisAbleEnum;
import com.huihe.common.exception.ServiceException;
import com.huihe.common.utils.MessageUtils;
import com.huihe.storage.dto.LoginUser;
import com.huihe.storage.entity.SysUser;
import com.huihe.storage.repository.SysUserRepository;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

/**
 * 用户验证处理
 * AuthenticationManager会使用该类的loadUserByUsername方法
 * 日志格式 :
 *     [LOGI] : login 登录
 *     [UPVE] : username password verify 用户名、密码 验证
 */
@Slf4j
@Service
@AllArgsConstructor
public class UserDetailsServiceImpl implements UserDetailsService {

    /**
     * 用户信息 Service层
     */
    SysUserRepository sysUserRepository;

    /**
     * 密码 Service 层
     */
    PasswordService passwordService;

    /**
     * 继承自 UserDetailsService 的方法
     * 用来查询并返回用户信息
     * @param username 用户名
     * @return 用户信息
     * @throws UsernameNotFoundException 异常
     */
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        // 1. 从数据库中进行条件查询
        SysUser sysUser = sysUserRepository.findByUserName(username);
        // 2. 判断用户是否存在
        if (sysUser == null){
            log.error("[LOGI] [UPVE] 登录用户:({}) 不存在",username);
            throw new ServiceException(MessageUtils.message("user.not.exists"));
        }
        // 3. 判断用户信息是否删除
        else if (DelFlagEnum.DELETED.getCode().equals(sysUser.getDelFlag())){
            log.error("[LOGI] [UPVE] 登录用户:({}) 已被删除",username);
            throw new ServiceException(MessageUtils.message("user.password.delete"));
        }
        // 4. 判断用户是否已被禁用
        else if (DisAbleEnum.DISABLE.getCode().equals(sysUser.getStatus())){
            log.error("[LOGI] [UPVE] 登录用户:({}) 已被禁用",username);
            throw new ServiceException(MessageUtils.message("user.blocked"));
        }
        // 6. 检验该登录请求的用户是否因为多次尝试但密码错误导致锁定
        passwordService.validate(sysUser);
        // 7. 创建一个用户信息对象，供 Spring Security 的 PasswordEncoder 类来验证
        return createLoginUser(sysUser);
    }

    /**
     * 创建一个实现 Spring Security 接口的类，用来保存用户的信息
     * @param sysUser 从数据库查询的信息
     * @return 实现 UserDetails 接口的对象
     */
    public UserDetails createLoginUser(SysUser sysUser){
        return new LoginUser(sysUser.getId(), sysUser);
    }
}
